/**
 * 
 */
package controller.xml;

import model.cnf.Stat;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

/**
 * Use to parse a {@link Stat} in the exported session in XML.
 * 
 * @author GRONOWSKI Stephane svan001@aol.com
 * 
 *         igsat 2010
 * 
 */
public class StatXMLHandler extends XMLHandler {

	private Stat			stat	= new Stat();
	private StatXMLStatus	status	= StatXMLStatus.NONE;


	@Override
	public boolean characters2(char[] ch, int start, int length) throws SAXException {

		switch (status) {
		case NONE:
			throw new SAXException("not supposed to receive character in this status");
		default:
			return super.characters2(ch, start, length);
		}
	}

	@Override
	public boolean endDocument2() throws SAXException {
		return false;
	}

	@Override
	public boolean endElement2(String uri, String localName, String qName) throws SAXException {
		switch (status) {
		case NONE:
			return false;

		case LITERAL:
			if (qName.equals(XMLBaliseFormat.CNF_NUM_LITERAL))
			{// ferme literal
				setLiteral();
				status = StatXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of LITERAL was expected");

		case CLAUSE:
			if (qName.equals(XMLBaliseFormat.CNF_NUM_CLAUSE))
			{// ferme clause
				setClause();
				status = StatXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of CLAUSE was expected");

		case UNIT_CLAUSE:
			if (qName.equals(XMLBaliseFormat.CNF_NUM_UNIT_CLAUSE))
			{// ferme unit clause
				setUnitCLause();
				status = StatXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of LITERAL was expected");

		case BINARY_CLAUSE:
			if (qName.equals(XMLBaliseFormat.CNF_NUM_BINARY_CLAUSE))
			{// ferme binary clause
				setBinaryclause();
				status = StatXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of BINARY CLAUSE was expected");

		case VAR:
			if (qName.equals(XMLBaliseFormat.CNF_NUM_VAR))
			{// ferme var
				setVar();
				status = StatXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of VAR was expected");

		case AVERAGE:
			if (qName.equals(XMLBaliseFormat.CNF_AVERAGE_LIT_CLAUSE))
			{// ferme average
				setAverage();
				status = StatXMLStatus.NONE;
				return true;
			}
			throw new SAXException("end of AVERAGE was expected");
		}

		// attend une fin de balise qui existe pas...
		throw new SAXException("an other end of element was expected");
	}


	@Override
	public boolean startElement2(String arg0, String arg1, String arg2, Attributes arg3) throws SAXException {
		if (status != StatXMLStatus.NONE)
			throw new SAXException("already have a started element");

		if (arg2.equals(XMLBaliseFormat.CNF_NUM_LITERAL))
		{// balise literal
			status = StatXMLStatus.LITERAL;
			return true;
		}

		if (arg2.equals(XMLBaliseFormat.CNF_NUM_BINARY_CLAUSE))
		{// balise BINARY_CLAUSE
			status = StatXMLStatus.BINARY_CLAUSE;
			return true;
		}

		if (arg2.equals(XMLBaliseFormat.CNF_NUM_CLAUSE))
		{// balise CLAUSE
			status = StatXMLStatus.CLAUSE;
			return true;
		}

		if (arg2.equals(XMLBaliseFormat.CNF_NUM_UNIT_CLAUSE))
		{// balise UNIT_CLAUSE
			status = StatXMLStatus.UNIT_CLAUSE;
			return true;
		}

		if (arg2.equals(XMLBaliseFormat.CNF_NUM_VAR))
		{// balise NUM_VAR
			status = StatXMLStatus.VAR;
			return true;
		}

		if (arg2.equals(XMLBaliseFormat.CNF_AVERAGE_LIT_CLAUSE))
		{// balise AVERAGE_LIT_CLAUSE
			status = StatXMLStatus.AVERAGE;
			return true;
		}
		// peut pas commencer balise qui existe pas
		throw new SAXException("unexpected balise: " + arg2);
	}


	/**
	 * Set the number of literal.
	 * 
	 * @throws SAXException
	 */
	private void setLiteral() throws SAXException {
		try
		{
			stat.setNumLiteral(Integer.valueOf(buffer.toString()));
		} catch (Exception e)
		{
			throw new SAXException("bad integer value for LITERAL");
		}
	}

	/**
	 * Set the number of clause.
	 * 
	 * @throws SAXException
	 */
	private void setClause() throws SAXException {
		try
		{
			stat.setNumClause(Integer.valueOf(buffer.toString()));
		} catch (Exception e)
		{
			throw new SAXException("bad integer value for CLAUSE");
		}
	}

	/**
	 * Set the number of unit clause.
	 * 
	 * @throws SAXException
	 */
	private void setUnitCLause() throws SAXException {
		try
		{
			stat.setNumUnitClause(Integer.valueOf(buffer.toString()));
		} catch (Exception e)
		{
			throw new SAXException("bad integer value for UNIT CLAUSE");
		}
	}

	/**
	 * Set the number of binary clause.
	 * 
	 * @throws SAXException
	 */
	private void setBinaryclause() throws SAXException {
		try
		{
			stat.setNumBinaryClause(Integer.valueOf(buffer.toString()));
		} catch (Exception e)
		{
			throw new SAXException("bad integer value for BINARY CLAUSE");
		}
	}

	/**
	 * Set the number of variable.
	 * 
	 * @throws SAXException
	 */
	private void setVar() throws SAXException {
		try
		{
			stat.setNumVar(Integer.valueOf(buffer.toString()));
		} catch (Exception e)
		{
			throw new SAXException("bad integer value for VAR");
		}
	}

	/**
	 * Set the average of literal per clause.
	 * 
	 * @throws SAXException
	 */
	private void setAverage() throws SAXException {
		try
		{
			stat.setAverageNumOfLiteralPerClause(Double.valueOf(buffer.toString()));
		} catch (Exception e)
		{
			throw new SAXException("bad integer value for AVERAGE");
		}
	}

	/**
	 * Return the stat.
	 * 
	 * @return the stat
	 */
	public Stat getStat() {
		return stat;
	}


}
